<?php

namespace app\common\controller\Cron;

use think\facade\Cache;
use app\common\model\User;
use app\common\model\BonusLog;
use app\common\model\Config;
use think\facade\Db;

class CronServer
{

    /*
     *  统计分红(每小时一次)
     * */
    public function staticBonusCron()
    {
        set_time_limit(0);
        $nowtime = time();
        $nowhour = date("YmdH", $nowtime);
        $c_time = strtotime($nowhour.":00:00");
        if (Cache::get($nowhour)) {
            return false;
        }
        Cache::set($nowhour, 1, 3600);
        $bonusLogModel = new BonusLog();
        if ($bonusLogModel->where("date", $nowhour)->count()) {
            Cache::delete($nowhour);
            return false;
        }
        $hour_bonus_num = config("dbconfig.sys.bonus_num");
        $configModel = new Config();
        $sur_token = $configModel->poolAll();
        $sur_token = $sur_token < 0? 0:$sur_token;
        if($hour_bonus_num > $sur_token){
            $hour_bonus_num = $sur_token;
        }
        if($hour_bonus_num <= 0){
            Cache::delete($nowhour);
            return false;
        }

        $bonusLogModel->startTrans();
        try {
            $log_id = $bonusLogModel->insertGetId([
                'date' => $nowhour,
                'c_time' => $c_time,
                'all_token' => $hour_bonus_num,
            ]);
            if (!$log_id) {
                Cache::delete($nowhour);
                $bonusLogModel->rollback();
                return false;
            }
            $userModel = new User();
            $all_lp = $userModel->sum("lp_amount");
            $suffix = $this->getBonusTableSuffix();
            $bonus_detail_table = "bonus_detail_list{$suffix}";
            $bonus_detail_num = Db::name($bonus_detail_table)->count();
            $max_num = 990 * 10000;
            if($bonus_detail_num >= $max_num){
                $bonus_detail_table_res = $this->createBonusDetailTable();
                $bonus_detail_table = str_replace("kulei_","",$bonus_detail_table_res['table']);
                $suffix = $bonus_detail_table_res['suffix'];
            }
            $devide_bonus_token = 0;
            if($all_lp > 0){
                $page = 0;
                while(1){
                    $page += 1;
                    $list_res = $userModel->where([['lp_amount','>',0]])->page($page,1000)->field("id,lp_amount")->select()->toArray();
                    $res_num = count($list_res);
                    if($res_num == 0){
                        break;
                    }
                    $insert_data = [];
                    foreach ($list_res as $k => $v){
                        $lp_rate = getRate($v['lp_amount'], $all_lp)/100;
                        $token = floor($hour_bonus_num * $lp_rate * 1000000)/1000000;
                        $devide_bonus_token += $token;
                        $insert_data[] = [
                            'log_id' => $log_id,
                            'uid' => $v['id'],
                            'lp' => $v['lp_amount'],
                            'c_time' => $c_time,
                            'c_date' => date("Ymd",$nowtime),
                            'token' => $token,
                            'all_lp' => $all_lp,
                        ];
                        if(($k+1)%500 == 0 || ($k+1) >= $res_num){
                            Db::name($bonus_detail_table)->insertAll($insert_data);
                        }
                    }
                    unset($list_res);
                }
            }
            $bonusLogModel->where("id", $log_id)->update([
                'all_lp' => $all_lp,
                'real_token_num' => $devide_bonus_token,
                'status' => 2,
                'suffix' => $suffix
            ]);
            $new_sur_token = $sur_token - $devide_bonus_token;
            $new_sur_token = $new_sur_token < 0?0:$new_sur_token;
            $configModel->where("k","pool_all_token")->update(["v" => $new_sur_token]);
            Cache::delete($nowhour);
            $bonusLogModel->commit();
            return true;
        } catch (\Exception $e) {
            Cache::delete($nowhour);
            $bonusLogModel->rollback();
            return false;
        }
    }

    /*
     *  发放分红(10分钟一次)
     * */
    public function divideBonusCron(){

        set_time_limit(0);
        $cache_key = "divideBonusCron";
        if(Cache::get($cache_key)){
            return false;
        }
        Cache::set($cache_key,1,7200);
        $bonusLogModel = new BonusLog();
        $log_info = $bonusLogModel->where("status",2)->field("id,suffix")->find();
        $log_id = $log_info['id'] ?? 0;
        $suffix = $log_info['suffix'] ?? '';
        if(empty($log_id)){
            Cache::delete($cache_key);
            return false;
        }
        $userServer = new \app\common\controller\User\UserServer();
        try {
            $bonus_detail_table = "bonus_detail_list{$suffix}";
            if($this->tableIsExist("kulei_".$bonus_detail_table)){
                $list = Db::name($bonus_detail_table)->where([['log_id','=',$log_id],['status','=',0]])->limit(500)->field("id,uid,token")->select();
                if(count($list) > 0){
                    $succ_id_arr = [];
                    foreach($list as $k => $v){
                        if($v['token'] > 0){
                            $res = $userServer->fundLog([
                                'uid' => $v['uid'],
                                'type' => 1,
                                'money' => $v['token'],
                                'detail' => '挖矿收益',
                                'note' => $v['id'],
                            ]);
                            if($res['code'] == 1){
                                $succ_id_arr[] = $v['id'];
                            }
                        }else{
                            $succ_id_arr[] = $v['id'];
                        }
                    }
                    if(!empty($succ_id_arr)){
                        Db::name($bonus_detail_table)->where("id","in", implode(",",$succ_id_arr))->update([
                            'status' => 1
                        ]);
                    }
                }
            }
            $bonusLogModel->where("id", $log_id)->update([
                'status' => 1
            ]);
            Cache::delete($cache_key);
            return true;
        }catch (\Exception $e){
            Cache::delete($cache_key);
            return false;
        }
    }

    /*
     *  创建分红记录表
     * */
    public function createBonusDetailTable()
    {
        $suffix = $this->getBonusTableSuffix();
        try {
            $suffix += 1;
            $sql = "CREATE TABLE `kulei_bonus_detail_list{$suffix}` (
             `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
              `log_id` int(10) unsigned NOT NULL DEFAULT '0',
              `uid` int(10) unsigned NOT NULL DEFAULT '0',
              `lp` decimal(24,6) unsigned NOT NULL DEFAULT '0.000000' COMMENT 'lp数量',
              `token` decimal(24,6) unsigned NOT NULL DEFAULT '0.000000' COMMENT '收益',
              `c_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '发放时间',
              `c_date` char(8) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '8',
              `status` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '1--已发放',
              `all_lp` decimal(30,6) unsigned NOT NULL DEFAULT '0.000000' COMMENT '总令牌数',
              PRIMARY KEY (`id`),
              KEY `uid` (`uid`) USING BTREE,
              KEY `log_id` (`log_id`) USING BTREE,
              KEY `c_date` (`c_date`) USING BTREE
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='挖矿详情表（收益表）';";

            Db::query($sql);
            Db::name("config")->where("k","bonus_detail_table_num")->update(['v' => $suffix]);
        }catch (\Exception $e){
        }
        return ['table' => "kulei_bonus_detail_list{$suffix}", 'suffix' => $suffix];
    }

    public function getBonusTableSuffix(){
        return Db::name("config")->where("k","bonus_detail_table_num")->value("v");
    }

    /*
     *  判断表格是否存在
     * */
    public function tableIsExist($table){
        if(Db::query('show tables like "'.$table.'"')){
            return true;
        }
        return false;
    }

    /*
     *  查询提现转账结果(5分钟一次)
     * */
    public function cashTranferResult(){

        set_time_limit(0);
        $cache_key = 'cron_cashTranferResult';
        if(Cache::get($cache_key)){
            return false;
        }
        Cache::set($cache_key,1,1200);
        try {
            $end_time = time()-30;
            $where = [];
            $where[] = ['c_time', '<', $end_time];
            $where[] = ['status', '=', 0];
            $cashList = new \app\common\model\CashList();
            $list = $cashList->where($where)->order("c_time desc")->limit(500)->field("id,uid,token_money,trade_hash")->select()->toArray();
            if(count($list) == 0){
                Cache::delete($cache_key);
                return false;
            }
            $userServer = new \app\common\controller\User\UserServer();
            foreach ($list as $k => $v){
                $status = 2;
                if(!empty($v['trade_hash'])){
                    $s_res = $userServer->querytranfersByHash($v['trade_hash']);
                    $status = 0;
                    if($s_res == 1){
                        $status = 1;
                    }elseif($s_res == 0){
                        $status = 2;
                    }
                }

                if($status == 0 && $v['status'] == 0 && $v['c_time'] - time() > 300){
                    $status = 2;
                }

                if($status > 0){
                    $this->updateCashStatus($v['id'],$v['uid'],$v['token_money'],$status);
                }
            }
            Cache::delete($cache_key);
            return true;
        }catch (\Exception $e){
            Cache::delete($cache_key);
            return false;
        }
    }

    public function updateCashStatus($cash_id,$uid,$token,$status){
        $cashList = new \app\common\model\CashList();
        $update_data = [
            'status' => $status
        ];
        $cashList->where([['id','=',$cash_id]])->update($update_data);
        $userServer = new \app\common\controller\User\UserServer();
        if($status == 2 && $token > 0){//退款
            $userServer->fundLog([
                'uid' => $uid,
                'type' => 3,
                'money' => $token,
                'detail' => '提取失败退回',
                'note' => $cash_id
            ]);
        }
        return true;
    }

    /*
     *  质押/解押转账结果(5分钟一次)
     * */
    public function pledgeTranferResult(){
        set_time_limit(0);
        $cache_key = 'cron_pledgeTranferResult';
        if(Cache::get($cache_key)){
            return false;
        }
        Cache::set($cache_key,1,1200);
        $res = $this->pledgeTranferResultRun();
        Cache::delete($cache_key);
        return $res;
    }


    /*
    *  质押/解押转账结果
    * */
    public function pledgeTranferResultRun($uid = 0){
        try {
            $end_time = time() - 30;
            $where = [];
            $where[] = ['status','=',0];
            $where[] = ['c_time', '<', $end_time];
            if($uid > 0){
                $where[] = ['uid','=',$uid];
            }
            $cashList = new \app\common\model\LpCashList();
            $list = $cashList->where($where)->order("c_time desc")->limit(500)->select()->toArray();
            if(count($list) == 0){
                return false;
            }
            $userServer = new \app\common\controller\User\UserServer();
            foreach ($list as $k => $v){
                $status = 2;
                $money = 0;
                if(!empty($v['trade_hash']) && strtolower($v['trade_hash']) != 'null'){
                    if($v['type'] == 1){//质押
                        $hash_res = $userServer->querytranfersByHash($v['trade_hash'],0);
                        $status = 0;
                        if(!empty($hash_res) && is_array($hash_res)){
                            $status = 2;
                            $check_res = $this->checkPledgeIsReal($hash_res, $v['from_address'], $v['to_address']);
                            if($check_res['code'] == 1 && $check_res['money'] > 0){
                                $status = 1;
                                $money = $check_res['money'];
                            }
                        }
                    }else{
                        $s_res = $userServer->querytranfersByHash($v['trade_hash']);
                        $status = 0;
                        if($s_res == 1){
                            $status = 1;
                        }elseif($s_res == 0){
                            $status = 2;
                        }
                    }
                }

                if($status == 0 && $v['status'] == 0 && $v['c_time'] - time() > 300){
                    $status = 2;
                }


                if($status > 0){
                    $this->updatePledgeStatus($v['id'], $v['type'],$v['uid'], $money, $status);
                }
            }
            return true;
        }catch (\Exception $e){
            return false;
        }
    }


    public function updatePledgeStatus($id,$type, $uid, $money, $status){
        $cashList = new \app\common\model\LpCashList();
        $update_data = [
            'status' => $status,
            'real_money' => $money,
        ];
        $cashList->where([['id','=', $id]])->update($update_data);
        $lpFundLog = new \app\common\model\LpFundLog();
        if($type == 2){//解压
            if($status == 2 && $money > 0){//退款
                $add_fund_data = [
                    'uid' => $uid,
                    'money' => $money,
                    'type' => 3,
                    'detail' => '解押失败',
                    'note' => $id
                ];
            }
        }elseif($type == 1 && $status == 1 && $money > 0){//质押
            $add_fund_data = [
                'uid' => $uid,
                'money' => $money,
                'type' => 1,
                'detail' => '质押',
                'note' => $id
            ];
        }

        if(!empty($add_fund_data)){
            $lpFundLog->addFundLog([
                'uid' => $uid,
                'money' => $money,
                'type' => 1,
                'detail' => '质押',
                'note' => $id
            ]);
        }
        return true;
    }

    /*
     *  检查质押交易的真实性和结果
     *  return bool true -- 成功； false--失败
     * */
    public function checkPledgeIsReal($data, $from_address, $to_address){

        try{
//            $to_address = strtolower($to_address);
            $from_address = strtolower($from_address);
            $config_contract_address = strtolower(config("dbconfig.sys.lp_contract_address"));

            $from = strtolower($data['from'] ?? '');
            $l_contract_address = strtolower($data['to'] ?? '');
            $status = $data['status'] ?? '';
            $value = empty($data['logs'][0]['data'])? '' : $data['logs'][0]['data'];
            $to = empty($data['logs'][0]['topics'][2])? '' : $data['logs'][0]['topics'][2];
            $heco = new \Heco();
            $status = $heco->hexToDec($status);
            $to_address = $heco->toAddressFormat($to_address);
            $to = strtolower($to);
            $to_address = strtolower("0x".$to_address);

            $decimal = $heco->contractDecimal(config("dbconfig.sys.lp_contract_address"));
            $value = $heco->hexToDec($value);
            $value = bcdiv($value, bcpow(10,$decimal),6);
            if($status != 1 || $from_address != $from || $to_address != $to || $l_contract_address != $config_contract_address){
                $code = 0;
            }else{
                $code = 1;
            }
            return ['code' => $code, 'money' => $value];
        }catch (\Exception $e){
            return ['code' => 0,'money' => 0];
        }
    }

}